home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / EXAMPLES / MJKSIFT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  6.6 KB  |  262 lines

  1.  
  2. /* Copyright (c) Mark J. Kilgard, 1994.  */
  3.  
  4. /* This program is freely distributable without licensing fees 
  5.    and is provided without guarantee or warrantee expressed or 
  6.    implied. This program is -not- in the public domain. */
  7.  
  8. /* This program uses 3D texture coordinates to introduce
  9.    "sifting" effects to warp a static mesh of textured
  10.    geometry.  The third texture coordinate encodes a shifting
  11.    quantity through the mesh.  By updating the texture matrix,
  12.    the texture coordinates can be shifted based on this
  13.    third texture coordinate.  You'll notice the face seems
  14.    to have local vortexes scattered over the image that
  15.    warp the image.  While the texture coordinates look dynamic,
  16.    they are indeed quite static (frozen in a display list) and
  17.    it is just the texture matrix that is changing to shift
  18.    the final 2D texture coordinates. */
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <math.h>       /* for cos(), sin(), and sqrt() */
  24. #include <GL/glut.h>
  25.  
  26. extern unsigned char mjk_image[];
  27. extern int mjk_depth;
  28. extern int mjk_height;
  29. extern int mjk_width;
  30.  
  31. float tick1 = 0;
  32. float tick2 = 0;
  33. float angle;
  34. float size = 0.4;
  35. int set_timeout = 0;
  36. int visible = 0;
  37. int sifting = 1;
  38. int scaling = 0;
  39. int interval = 100;
  40.  
  41. void
  42. animate(int value)
  43. {
  44.   if (visible) {
  45.     if (sifting || scaling) {
  46.       if (value) {
  47.         if (sifting) {
  48.           tick1 += 4 * (interval / 100.0);
  49.           angle = ((int) tick1) % 360;
  50.         }
  51.         if (scaling) {
  52.           tick2 += 2 * (interval / 100.0);
  53.           size = .7 - .5 * sin(tick2 / 20.0);
  54.         }
  55.       }
  56.       glutPostRedisplay();
  57.       set_timeout = 1;
  58.     }
  59.   }
  60. }
  61.  
  62. /* Setup display list with "frozen" 3D texture coordinates. */
  63. void
  64. generateTexturedSurface(void)
  65. {
  66.   static GLfloat data[8] =
  67.   {0, 1, 0, -1};
  68.   int i, j;
  69.  
  70. #define COLS 12
  71. #define ROWS 12
  72. #define TILE_TEX_W (1.0/COLS)
  73. #define TILE_TEX_H (1.0/ROWS)
  74.  
  75.   glNewList(1, GL_COMPILE);
  76.   glTranslatef(-COLS / 2.0 + .5, -ROWS / 2.0 + .5, 0);
  77.   for (j = 0; j < ROWS; j++) {
  78.     glBegin(GL_QUAD_STRIP);
  79.     for (i = 0; i < COLS; i++) {
  80.       glTexCoord3f(i * TILE_TEX_W, j * TILE_TEX_H, data[(i + j) % 4]);
  81.       glVertex2f(i - .5, j - .5);
  82.       glTexCoord3f(i * TILE_TEX_W, (j + 1) * TILE_TEX_H, data[(i + j + 1) % 4]);
  83.       glVertex2f(i - .5, j + .5);
  84.     }
  85.     glTexCoord3f((i + 1) * TILE_TEX_W, j * TILE_TEX_H, data[(i + j) % 4]);
  86.     glVertex2f(i + .5, j - .5);
  87.     glTexCoord3f((i + 1) * TILE_TEX_W, (j + 1) * TILE_TEX_H, data[(i + j + 1) % 4]);
  88.     glVertex2f(i + .5, j + .5);
  89.     glEnd();
  90.   }
  91.   glEndList();
  92. }
  93.  
  94. /* Construct an identity matrix except that the third coordinate
  95.    can be used to "sift" the X and Y coordinates. */
  96. void
  97. makeSift(GLfloat m[16], float xsift, float ysift)
  98. {
  99.   m[0 + 4 * 0] = 1;
  100.   m[0 + 4 * 1] = 0;
  101.   m[0 + 4 * 2] = xsift;
  102.   m[0 + 4 * 3] = 0;
  103.  
  104.   m[1 + 4 * 0] = 0;
  105.   m[1 + 4 * 1] = 1;
  106.   m[1 + 4 * 2] = ysift;
  107.   m[1 + 4 * 3] = 0;
  108.  
  109.   m[2 + 4 * 0] = 0;
  110.   m[2 + 4 * 1] = 0;
  111.   m[2 + 4 * 2] = 1;
  112.   m[2 + 4 * 3] = 0;
  113.  
  114.   m[3 + 4 * 0] = 0;
  115.   m[3 + 4 * 1] = 0;
  116.   m[3 + 4 * 2] = 0;
  117.   m[3 + 4 * 3] = 1;
  118. }
  119.  
  120. void
  121. redraw(void)
  122. {
  123.   int begin, end, elapsed;
  124.   GLfloat matrix[16];
  125.  
  126.   if (set_timeout) {
  127.     begin = glutGet(GLUT_ELAPSED_TIME);
  128.   }
  129.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  130.   glPushMatrix();
  131.  
  132.   glScalef(size, size, size);
  133.  
  134.   glMatrixMode(GL_TEXTURE);
  135.   makeSift(matrix, 0.02 * cos(tick1 / 40.0), 0.02 * sin(tick1 / 15.0));
  136.   glLoadMatrixf(matrix);
  137.   glMatrixMode(GL_MODELVIEW);
  138.  
  139.   glCallList(1);
  140.  
  141.   glPopMatrix();
  142.   glutSwapBuffers();
  143.   if (set_timeout) {
  144.     set_timeout = 0;
  145.     end = glutGet(GLUT_ELAPSED_TIME);
  146.     elapsed = end - begin;
  147.     if (elapsed > interval) {
  148.       glutTimerFunc(0, animate, 1);
  149.     } else {
  150.       glutTimerFunc(interval - elapsed, animate, 1);
  151.     }
  152.   }
  153. }
  154.  
  155. int width;
  156. int height;
  157. int depth;
  158. unsigned char *bits;
  159.  
  160. void
  161. visibility(int state)
  162. {
  163.   if (state == GLUT_VISIBLE) {
  164.     visible = 1;
  165.     animate(0);
  166.   } else {
  167.     visible = 0;
  168.   }
  169. }
  170.  
  171. void
  172. minify_select(int value)
  173. {
  174.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, value);
  175.   gluBuild2DMipmaps(GL_TEXTURE_2D, depth, width, height,
  176.     GL_RGB, GL_UNSIGNED_BYTE, bits);
  177.   glutPostRedisplay();
  178. }
  179.  
  180. void
  181. rate_select(int value)
  182. {
  183.   interval = value;
  184. }
  185.  
  186. void
  187. menu_select(int value)
  188. {
  189.   switch (value) {
  190.   case 1:
  191.     sifting = !sifting;
  192.     if (sifting)
  193.       animate(0);
  194.     break;
  195.   case 2:
  196.     scaling = !scaling;
  197.     if (scaling)
  198.       animate(0);
  199.     break;
  200.   case 666:
  201.     exit(0);
  202.   }
  203. }
  204.  
  205. int
  206. main(int argc, char **argv)
  207. {
  208.   int minify_menu, rate_menu;
  209.  
  210.   glutInit(&argc, argv);
  211.   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  212.   glutCreateWindow("mjksift");
  213.   glutDisplayFunc(redraw);
  214.   glMatrixMode(GL_PROJECTION);
  215.   gluPerspective( /* field of view in degree */ 40.0,
  216.   /* aspect ratio */ 1.0,
  217.     /* Z near */ 1.0, /* Z far */ 70.0);
  218.   glMatrixMode(GL_MODELVIEW);
  219.   gluLookAt(0.0, 0.0, 5.0,  /* eye is at (0,0,30) */
  220.     0.0, 0.0, 0.0,      /* center is at (0,0,0) */
  221.     0.0, 1.0, 0.);      /* up is in positive Y direction */
  222.   depth = mjk_depth;
  223.   width = mjk_width;
  224.   height = mjk_height;
  225.   bits = mjk_image;
  226.   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  227.   gluBuild2DMipmaps(GL_TEXTURE_2D, depth, width, height,
  228.     GL_RGB, GL_UNSIGNED_BYTE, bits);
  229.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  230.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  231.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  232.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  233.   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  234.   glEnable(GL_TEXTURE_2D);
  235.   glutVisibilityFunc(visibility);
  236.   minify_menu = glutCreateMenu(minify_select);
  237.   glutAddMenuEntry("Nearest", GL_NEAREST);
  238.   glutAddMenuEntry("Linear", GL_LINEAR);
  239.   glutAddMenuEntry("Nearest mipmap nearest", GL_NEAREST_MIPMAP_NEAREST);
  240.   glutAddMenuEntry("Linear mipmap nearest", GL_LINEAR_MIPMAP_NEAREST);
  241.   glutAddMenuEntry("Nearest mipmap linear", GL_NEAREST_MIPMAP_LINEAR);
  242.   glutAddMenuEntry("Linear mipmap linear", GL_LINEAR_MIPMAP_LINEAR);
  243.   rate_menu = glutCreateMenu(rate_select);
  244.   glutAddMenuEntry(" 2/sec", 500);
  245.   glutAddMenuEntry(" 6/sec", 166);
  246.   glutAddMenuEntry("10/sec", 100);
  247.   glutAddMenuEntry("20/sec", 50);
  248.   glutAddMenuEntry("30/sec", 33);
  249.   glutAddMenuEntry("60/sec", 16);
  250.   glutCreateMenu(menu_select);
  251.   glutAddMenuEntry("Toggle sifting", 1);
  252.   glutAddMenuEntry("Toggle scaling", 2);
  253.   glutAddSubMenu("Minimum frame rate", rate_menu);
  254.   glutAddSubMenu("Minify modes", minify_menu);
  255.   glutAddMenuEntry("Quit", 666);
  256.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  257.   menu_select(3);
  258.   generateTexturedSurface();
  259.   glutMainLoop();
  260.   return 0;             /* ANSI C requires main to return int. */
  261. }
  262.